﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using TireService.Data;
using DevExpress.Web.ASPxGridView;
using DevExpress.Web.ASPxEditors;
using System.Configuration;
using DevExpress.Web.ASPxCallback;

namespace TireService.Web.View.ServiceView
{
    public partial class GroupServicePlanning : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

            TireServiceDB db = new TireServiceDB();

            if (Page.IsPostBack != true)
            {

            }

            // Bind groupservicecarschedule data to gridview
            BindGroupServiceCarScheduleData(db, cbAllGroupServiceCarSchedule.Checked);
            try
            {
                int GroupServiceCarScheduleId = Convert.ToInt32(gvGroupServiceCarSchedule.GetRowValues(gvGroupServiceCarSchedule.FocusedRowIndex, "GroupServiceCarScheduleId"));
                BindServiceCarSchedule(db, GroupServiceCarScheduleId);
            }
            catch (Exception)
            {
                // Nothing - no group servicecarschedule selected
            }

            try
            {
                int ContainerId = Convert.ToInt32(gvGroupServiceCarSchedule.GetRowValues(gvGroupServiceCarSchedule.FocusedRowIndex, "ContainerId"));
                BindServiceCarScheduleAvailable(db, ContainerId);
            }
            catch (Exception)
            {
                // Nothing - no group servicecarschedule selected
            }

            //// Change gridview pagesize based on dropdownlist
            //gvGroupServiceCarSchedule.SettingsPager.PageSize = Convert.ToInt32(ddlPageSize.SelectedValue);

            // Dispose connection to database
            db.Dispose();
        }

        /// <summary>
        /// Function that bind group servicecarschedule data to gridview
        /// </summary>
        /// <param name="db">Connection to database</param>
        private void BindGroupServiceCarScheduleData(TireServiceDB db, bool InActive)
        {
            gvGroupServiceCarSchedule.DataSource = db.GetGroupServiceCarSchedules(InActive);
            gvGroupServiceCarSchedule.DataBind();

            // Prepare data for editmode of record
            GridViewDataComboBoxColumn ddlCountry = gvGroupServiceCarSchedule.Columns["CountryDropdown"] as GridViewDataComboBoxColumn;
            ddlCountry.PropertiesComboBox.ValueType = typeof(int);
            ddlCountry.PropertiesComboBox.DataSource = db.GetCountries();
            ddlCountry.PropertiesComboBox.TextField = "CountryName";
            ddlCountry.PropertiesComboBox.ValueField = "CountryId";
            ddlCountry.PropertiesComboBox.DropDownStyle = DropDownStyle.DropDownList;
            ddlCountry.PropertiesComboBox.IncrementalFilteringMode = IncrementalFilteringMode.StartsWith;

            GridViewDataComboBoxColumn ddlContainer = gvGroupServiceCarSchedule.Columns["ContainerDropdown"] as GridViewDataComboBoxColumn;
            ddlContainer.PropertiesComboBox.ValueType = typeof(int);
            ddlContainer.PropertiesComboBox.DataSource = db.GetContainers();
            ddlContainer.PropertiesComboBox.TextField = "ContainerNumber";
            ddlContainer.PropertiesComboBox.ValueField = "ContainerId";
            ddlContainer.PropertiesComboBox.DropDownStyle = DropDownStyle.DropDownList;
            ddlContainer.PropertiesComboBox.IncrementalFilteringMode = IncrementalFilteringMode.StartsWith;

            // MIDLERTIDIG LØSNING - IKKE GOD IFHT. VALG AF KUNDE
            GridViewDataComboBoxColumn ddlCustomer = gvGroupServiceCarSchedule.Columns["CustomerDropdown"] as GridViewDataComboBoxColumn;
            ddlCustomer.PropertiesComboBox.ValueType = typeof(int);
            ddlCustomer.PropertiesComboBox.DataSource = db.GetCustomers();
            ddlCustomer.PropertiesComboBox.TextField = "CustomerId";
            ddlCustomer.PropertiesComboBox.ValueField = "CustomerId";
            ddlCustomer.PropertiesComboBox.DropDownStyle = DropDownStyle.DropDownList;
            ddlCustomer.PropertiesComboBox.IncrementalFilteringMode = IncrementalFilteringMode.StartsWith;

        }

        /// <summary>
        /// Function that bind servicecarschedule assigned to groupservicecarschedule to gridview
        /// </summary>
        /// <param name="db">Connection to database</param>
        /// <param name="GroupServiceCarScheduleId">Id on groupservicecarschedule</param>
        private void BindServiceCarSchedule(TireServiceDB db, int GroupServiceCarScheduleId)
        {
            // Bind to gridview
            gvServiceCarSchedule.DataSource = db.GetServiceCarSchedulesByGroupServiceCarScheduleId(GroupServiceCarScheduleId);
            gvServiceCarSchedule.DataBind();
        }

        /// <summary>
        /// Function that bind free servicecarschedules for assigning to group servicecarschedule to gridview
        /// </summary>
        /// <param name="db">Connection to database</param>
        /// <param name="containerid">Id on container - only show servicecars related to that container i result</param>
        private void BindServiceCarScheduleAvailable(TireServiceDB db, int containerid)
        {
            int[] scheduledetailtypes = new int[] { (int)Shared.ScheduleDetailType.Blocked, (int)Shared.ScheduleDetailType.ServiceDrive, (int)Shared.ScheduleDetailType.TireChange };

            var servicecarschedule = from p in db.ServiceCarSchedules
                                     join y in db.ContainerServiceCarCoverages on p.ServiceCarId equals y.ServiceCarId into py
                                     from z in py.DefaultIfEmpty()
                                     where z.ContainerId == containerid & p.ScheduleDate >= DateTime.Now & p.GroupServiceCarScheduleId == null & (db.ServiceCarScheduleDetails.Where(d => d.ServiceCarId == p.ServiceCarId & d.ScheduleDate == p.ScheduleDate & scheduledetailtypes.Contains(d.ScheduleDetailTypeId)).Count() == 0)
                                     select new
                                     {
                                         p.ServiceCarScheduleId,
                                         p.ServiceCarId,
                                         p.ScheduleDate,
                                         TotalCapacity = db.ServiceCarScheduleDetails.Where(q => q.ServiceCarId == p.ServiceCarId & q.ScheduleDate == p.ScheduleDate).Count(),
                                         FreeCapacity = db.ServiceCarScheduleDetails.Where(q => q.ServiceCarId == p.ServiceCarId & q.ScheduleDate == p.ScheduleDate & q.ScheduleDetailTypeId == (int)Shared.ScheduleDetailType.Available).Count(),
                                     };

            gvAvailableScheduleDates.DataSource = servicecarschedule.ToList();
            gvAvailableScheduleDates.DataBind();
        }

        ///// <summary>
        ///// Button function for export of gridview
        ///// </summary>
        //protected void btnExport_Click(object sender, EventArgs e)
        //{
        //    if (ddlExport.Value == "0")
        //    {
        //        gvExport.WritePdfToResponse();
        //    }

        //    if (ddlExport.Value == "1")
        //    {
        //        gvExport.WriteXlsToResponse();
        //    }

        //    if (ddlExport.Value == "2")
        //    {
        //        gvExport.WriteCsvToResponse();
        //    }

        //    if (ddlExport.Value == "3")
        //    {
        //        gvExport.WriteRtfToResponse();
        //    }
        //}

        #region GridView Functions

        /// <summary>
        /// Gridview function for callback on GroupServiceCarSchedule (master gridview)
        /// </summary>
        protected void gvGroupServiceCarSchedule_CustomCallback(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewCustomCallbackEventArgs e)
        {
            TireServiceDB db = new TireServiceDB();

            BindGroupServiceCarScheduleData(db, Convert.ToBoolean(e.Parameters));
        }

        /// <summary>
        /// Gridview function for creating groupservicecarschedule
        /// </summary>
        protected void gvGroupServiceCarSchedule_RowInserting(object sender, DevExpress.Web.Data.ASPxDataInsertingEventArgs e)
        {
            TireServiceDB db = new TireServiceDB();

            GroupServiceCarSchedule groupservicecarschedule = new GroupServiceCarSchedule();

            groupservicecarschedule.Description = Convert.ToString(e.NewValues["Description"]);
            groupservicecarschedule.Address = Convert.ToString(e.NewValues["Address"]);
            groupservicecarschedule.ZipCode = Convert.ToString(e.NewValues["ZipCode"]);
            groupservicecarschedule.City = Convert.ToString(e.NewValues["City"]);
            groupservicecarschedule.CountryId = Convert.ToInt32(e.NewValues["CountryId"]);
            groupservicecarschedule.InActive = Convert.ToBoolean(e.NewValues["InActive"]);
            groupservicecarschedule.ContainerId = Convert.ToInt32(e.NewValues["ContainerId"]);
            groupservicecarschedule.InfoOnCarParking = Convert.ToString(e.NewValues["InfoOnCarParking"]);

            // Calculate longitude and latitude for address
            try
            {
                string primaryAddress = groupservicecarschedule.Address + ", " + groupservicecarschedule.ZipCode + " " + groupservicecarschedule.City + ", " + db.GetCountryName(groupservicecarschedule.CountryId);
                GoogleMaps googleMapAPI = new GoogleMaps(ConfigurationSettings.AppSettings["MapKey"]);
                double[] LongLatPrimary = googleMapAPI.GetLongLatCoordinates(primaryAddress);
                groupservicecarschedule.Longitude = LongLatPrimary[0];
                groupservicecarschedule.Latitude = LongLatPrimary[1];
            }
            catch (Exception ex)
            {
                // Error calculating longitude and latitude - values will be set to null
            }

            //// Get customerId
            //ASPxComboBox ddlCustomer = (ASPxComboBox)gvGroupServiceCarSchedule.FindEditFormTemplateControl("ddlCustomer");
            //groupservicecarschedule.CustomerId = Convert.ToInt32(ddlCustomer.Value);
            groupservicecarschedule.CustomerId = Convert.ToInt32(e.NewValues["CustomerId"]);

            db.AddGroupServiceCarSchedule(groupservicecarschedule);

            // Commit changes to database
            db.SubmitChanges();

            // End edit mode
            e.Cancel = true;
            gvGroupServiceCarSchedule.CancelEdit();

            // Refresh gridview
            BindGroupServiceCarScheduleData(db, cbAllGroupServiceCarSchedule.Checked);

            // Close db connection
            db.Dispose();
        }

        /// <summary>
        /// Gridview function for updating groupservicecarschedule
        /// </summary>
        protected void gvGroupServiceCarSchedule_RowUpdating(object sender, DevExpress.Web.Data.ASPxDataUpdatingEventArgs e)
        {
            // Get id
            int GroupServiceCarScheduleId = Convert.ToInt32(e.Keys["GroupServiceCarScheduleId"]);

            TireServiceDB db = new TireServiceDB();

            GroupServiceCarSchedule groupservicecarschedule = new GroupServiceCarSchedule();

           

            // Fecth existing container tireset
            groupservicecarschedule = db.GetGroupServiceCarSchedule(GroupServiceCarScheduleId);

            if (groupservicecarschedule != null)
            {
                groupservicecarschedule.Description = Convert.ToString(e.NewValues["Description"]);
                groupservicecarschedule.Address = Convert.ToString(e.NewValues["Address"]);
                groupservicecarschedule.ZipCode = Convert.ToString(e.NewValues["ZipCode"]);
                groupservicecarschedule.City = Convert.ToString(e.NewValues["City"]);
                groupservicecarschedule.CountryId = Convert.ToInt32(e.NewValues["CountryId"]);
                groupservicecarschedule.InActive = Convert.ToBoolean(e.NewValues["InActive"]);
                groupservicecarschedule.ContainerId = Convert.ToInt32(e.NewValues["ContainerId"]);
                groupservicecarschedule.InfoOnCarParking = Convert.ToString(e.NewValues["InfoOnCarParking"]);

                // Calculate longitude and latitude for address if changed
                if (e.OldValues["Address"] != e.NewValues["Address"] | e.OldValues["ZipCode"] != e.NewValues["ZipCode"] | e.OldValues["City"] != e.NewValues["City"] | e.OldValues["CountryId"] != e.NewValues["CountryId"])
                {
                    try
                    {
                        string primaryAddress = groupservicecarschedule.Address + ", " + groupservicecarschedule.ZipCode + " " + groupservicecarschedule.City + ", " + db.GetCountryName(groupservicecarschedule.CountryId);
                        GoogleMaps googleMapAPI = new GoogleMaps(ConfigurationSettings.AppSettings["MapKey"]);
                        double[] LongLatPrimary = googleMapAPI.GetLongLatCoordinates(primaryAddress);
                        groupservicecarschedule.Longitude = LongLatPrimary[0];
                        groupservicecarschedule.Latitude = LongLatPrimary[1];
                    }
                    catch (Exception ex)
                    {
                        // Error calculating longitude and latitude - values will be set to null
                    }
                }
            }
            else
            {
                // Customer subscription does not exists
                throw new ArgumentException("Gruppe/firma kørsel eksistere ikke");
            }

            // Commit changes to database
            db.SubmitChanges();

            // End edit mode
            e.Cancel = true;
            gvGroupServiceCarSchedule.CancelEdit();

            // Refresh gridview
            BindGroupServiceCarScheduleData(db, cbAllGroupServiceCarSchedule.Checked);

            // Close db connection
            db.Dispose();
        }

        /// <summary>
        /// Gridview function for callback on ServiceCarSchedule (detail gridview)
        /// </summary>
        protected void gvServiceCarSchedule_CustomCallback(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewCustomCallbackEventArgs e)
        {
            TireServiceDB db = new TireServiceDB();
            try
            {
                int GroupServiceCarScheduleId = Convert.ToInt32(gvGroupServiceCarSchedule.GetRowValues(gvGroupServiceCarSchedule.FocusedRowIndex, "GroupServiceCarScheduleId"));
                BindServiceCarSchedule(db, GroupServiceCarScheduleId);
            }
            catch (Exception)
            {
                // Nothing - no group servicecarschedule selected
            }
        }

        /// <summary>
        /// Gridview function that change field data for unbound fields
        /// </summary>
        protected void gvServiceCarSchedule_CustomUnboundColumnData(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewColumnDataEventArgs e)
        {
            
            // Format UnBoundColumn FreeCapacity: Show free capacity
            if (e.Column.FieldName == "FreeCapacity")
            {
                TireServiceDB db = new TireServiceDB();

                DateTime ScheduleDate = Convert.ToDateTime(e.GetListSourceFieldValue("ScheduleDate"));
                int ServiceCarId = Convert.ToInt32(e.GetListSourceFieldValue("ServiceCarId"));

                int AvailableCapacity = db.ServiceCarScheduleDetails.Where(p => p.ServiceCarId == ServiceCarId & p.ScheduleDate == ScheduleDate & p.ScheduleDetailTypeId == (int)Shared.ScheduleDetailType.Available).Count();

                e.Value = AvailableCapacity.ToString();

                db.Dispose();
            }

            // Format UnBoundColumn FreeCapacity: Show total capacity
            if (e.Column.FieldName == "TotalCapacity")
            {
                TireServiceDB db = new TireServiceDB();

                DateTime ScheduleDate = Convert.ToDateTime(e.GetListSourceFieldValue("ScheduleDate"));
                int ServiceCarId = Convert.ToInt32(e.GetListSourceFieldValue("ServiceCarId"));

                int Capacity = db.ServiceCarScheduleDetails.Where(p => p.ServiceCarId == ServiceCarId & p.ScheduleDate == ScheduleDate).Count();

                e.Value = Capacity.ToString();
                
                db.Dispose();
            }
        }

        
        /// <summary>
        /// Gridview function for callback on 
        /// </summary>
        protected void gvAvailableScheduleDates_CustomCallback(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewCustomCallbackEventArgs e)
        {
            //TireServiceDB db = new TireServiceDB();
            //try
            //{
            //    int GroupServiceCarScheduleId = Convert.ToInt32(gvGroupServiceCarSchedule.GetRowValues(gvGroupServiceCarSchedule.FocusedRowIndex, "GroupServiceCarScheduleId"));
            //    BindServiceCarSchedule(db, GroupServiceCarScheduleId);
            //}
            //catch (Exception)
            //{
            //    // Nothing - no group servicecarschedule selected
            //}

        }

        #endregion

        #region Callback Panel Functions

        /// <summary>
        /// Callback function that deletes servicecarschedule from groupservicecarschedule
        /// </summary>
        protected void callDeleteServiceCarSchedule_Callback(object sender, CallbackEventArgs e)
        {
            TireServiceDB db = new TireServiceDB();

            // Get value (ServiceCarScheduleId)
            int ServiceCarScheduleId = Convert.ToInt32(e.Parameter);

            // Validate if any bookings has been made to scheduledetail
            // TODO: Write code - yes bookings exists, deletion can not be done or???

            // Delete servicecar geoarea allocation
            ServiceCarSchedule servicecarschedule = db.GetServiceCarSchedule(ServiceCarScheduleId);

            if (servicecarschedule != null)
            {
                // Remove group servicecarschedule
                servicecarschedule.GroupServiceCarScheduleId = null;

                db.SubmitChanges();
            }
            else
            {
                // Throw error message
                throw new ArgumentException("Udkørsel blev ikke fundet");
            }

            db.Dispose();
        }

        /// <summary>
        /// Function - callback that runs when create new service car allocation to group service carschedule that has been selected, bind none allocated service car schedules
        /// </summary>
        protected void callbackCreateServiceCarScheduleAllocationPanel_Callback(object source, DevExpress.Web.ASPxClasses.CallbackEventArgsBase e)
        {
            TireServiceDB db = new TireServiceDB();

            int containerid = Convert.ToInt32(e.Parameter);

            BindServiceCarScheduleAvailable(db, containerid);
        }

        /// <summary>
        /// Callback function that adds servicecarschedule to groupservicecarschedule
        /// </summary>
        protected void callbackAddServiceCarSchedule_Callback(object sender, CallbackEventArgs e)
        {
            // Get values (ServiceCarScheduleId, GroupServiceCarScheduleId)
            int ServiceCarScheduleId = Convert.ToInt32(e.Parameter);
            int GroupServiceCarScheduleId = Convert.ToInt32(gvGroupServiceCarSchedule.GetRowValues(gvGroupServiceCarSchedule.FocusedRowIndex, "GroupServiceCarScheduleId"));

            TireServiceDB db = new TireServiceDB();

            ServiceCarSchedule schedule = db.GetServiceCarSchedule(ServiceCarScheduleId);

            if (schedule == null)
            {
                // Throw error message
                throw new ArgumentException("Kørselsdag for service bil ikke fundet");
            }
            else
            {
                schedule.GroupServiceCarScheduleId = GroupServiceCarScheduleId;

                db.SubmitChanges();
            }

            db.Dispose();
        }

        #endregion
    }
}